1/* 2* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. 3* Licensed under the Apache License, Version 2.0 (the "License"); 4* you may not use this file except in compliance with the License. 5* You may obtain a copy of the License at 6* 7* http://www.apache.org/licenses/LICENSE-2.0 8* 9* Unless required by applicable law or agreed to in writing, software 10* distributed under the License is distributed on an "AS IS" BASIS, 11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12* See the License for the specific language governing permissions and 13* limitations under the License. 14*/ 15const childProcess = require('child_process'); 16const fs = require('fs'); 17const path = require('path'); 18const { AnalyzeCommand } = require('./analyze_command'); 19const { Logger } = require('./logger'); 20const { Tool } = require('./tool'); 21 22class AnalyzeMake { 23 constructor() { 24 25 } 26 27 static USE_UDP_COLLECTOR = true; 28 static collectByUdp(makeProjectPath) { 29 const dgram = require('dgram'); 30 let udpServer_ = dgram.createSocket('udp4'); 31 let analyzeResult = []; 32 udpServer_.bind(6000); 33 udpServer_.on('listening', () => { 34 Tool.pushd(makeProjectPath); 35 let ret = childProcess.spawn(Tool.getMake(), ['-C', makeProjectPath, '-n']); 36 ret.stdout.on('data', (data) => {//要有,不然不进入close 37 }); 38 ret.stderr.on('data', (data) => { 39 Logger.err(data.toString()); 40 }); 41 ret.on('close', (code) => { 42 if (code === 0) { 43 Logger.info('-----------------------------make ok'); 44 udpServer_.close(); 45 udpServer_ = null; 46 47 AnalyzeCommand.storeCommands(); 48 49 Tool.generateTarget(makeProjectPath, analyzeResult);//生成结果目标 50 } else { 51 Logger.err('make fail'); 52 } 53 }); 54 }); 55 udpServer_.on('error', (e) => { 56 Logger.err('udp error'); 57 }); 58 udpServer_.on('message', (msg, rinfo) => { 59 let acmd = msg.toString(); 60 let ret = AnalyzeCommand.analyze(acmd);//解析命令msg 61 if (ret.length > 0) { 62 analyzeResult.push(...ret); 63 } 64 udpServer_.send('ok', 0, 2, rinfo.port, rinfo.address);//反馈ok给make继续执行 65 }); 66 } 67 static analyzeBreakup() { 68 let acmd = ''; 69 for (let l of dlist) { 70 if (l.endsWith('\\')) { // 合并带有换行符的命令 71 acmd += l; 72 } 73 else { 74 acmd = getAcmd(acmd, l); 75 } 76 } 77 } 78 static analyze(makeProjectFile) { 79 let makeProjectPath = path.parse(makeProjectFile); 80 if (!fs.existsSync(makeProjectFile)) { 81 Logger.err('Makefile not exist in ' + makeProjectPath.dir); 82 return; 83 } 84 if (AnalyzeMake.USE_UDP_COLLECTOR) { 85 AnalyzeMake.collectByUdp(makeProjectPath.dir); 86 return; 87 } 88 Tool.pushd(makeProjectPath.dir); 89 let ret = childProcess.spawn('make', ['-C', makeProjectPath.dir, '-n']); 90 let cmdlist = []; 91 let analyzeResult = []; 92 let procData = ''; 93 ret.stdout.on('data', (data) => { 94 procData += data.toString(); 95 let p = procData.lastIndexOf('\n'); 96 if (p < 0) { 97 return; 98 } 99 let dlist = procData.substring(0, p).split('\n'); 100 procData = procData.substring(p + 1); 101 AnalyzeMake.analyzeBreakup(dlist, cmdlist, analyzeResult); 102 }); 103 ret.stderr.on('data', (data) => { 104 Logger.err(data.toString()); 105 }); 106 ret.on('close', (code) => { 107 if (code === 0) { 108 Logger.info('-----------------------------make ok'); 109 Tool.generateTarget(makeProjectPath.dir, analyzeResult);//生成结果目标 110 } else { 111 Logger.err('make fail'); 112 } 113 }); 114 } 115} 116 117function getAcmd(acmd, l) { 118 acmd += l; 119 if (acmd.length > 0) { 120 cmdlist.push(acmd); 121 let ret = AnalyzeCommand.analyze(acmd); 122 if (ret.length > 0) { 123 analyzeResult.push(...ret); 124 } 125 } 126 acmd = ''; 127 return acmd; 128} 129 130module.exports = { 131 AnalyzeMake 132};