"Options:\n"
" --mibc - Specify Mibc files. Sepatated with ':'.\n"
" --verbose - Display verbose information\n"
- " --inputbubble - Use inputbubble\n"
- " --inputbubbleref - Path of references for inputbubble (used with --inputbubble option)\n"
- " (If not set, all references are included to inputbubble.)\n"
- " --ref - Path of references\n"
- " (If not set, default system paths are used.)\n"
+ " --inputbubble - Compile input assemblies into one bubble with the assemblies described at --inputbubbleref option\n"
+ " Note!: If you do not have an accurate understanding of Bubble, do not use this option.\n"
+ " All assemblies in the bubble must be guaranteed to be compiled to the native image before execution.\n"
+ " If an uncompiled assembly is included in the bubble during execution, an unknown error may occur.\n"
+ " If --inputbubbleref option doesnot be set, only input files are included to bubble. \n"
+ " --inputbubbleref - Input bubble reference file(s) to be added to bubble (used with --inputbubble option)\n"
+ " --ref - Reference file(s) for compilation\n"
+ " (system paths are set automatically.)\n"
" --no-pipeline - Compile the dlls individually\n"
" --print-cmd - Print command and options\n"
" --skip-ro-app - Skip re-generate NI for apps installed RO area\n"
opt->flags |= NI_FLAGS_INPUT_BUBBLE_REF;
- std::vector<std::string> paths;
- splitPath(std::string(argv[i]), paths);
- for (const auto &path : paths) {
- if (!isDirectory(path)) {
- _SERR("intpubbubbleref path is missing or not exist");
- return -1;
- }
- opt->inputBubbleRefPath.push_back(path);
+ std::vector<std::string> files;
+ splitPath(std::string(argv[i]), files);
+ for (const auto &f : files) {
+ opt->inputBubbleRefFiles.push_back(f);
}
} else if (arg == "--ref") {
++i;
return 0;
}
- opt->flags |= NI_FLAGS_REF;
-
- std::vector<std::string> paths;
- splitPath(std::string(argv[i]), paths);
- for (const auto &path : paths) {
- if (!isDirectory(path)) {
- _SERR("ref path is missing or not exist");
- return -1;
- }
- opt->refPath.push_back(path);
+ std::vector<std::string> files;
+ splitPath(std::string(argv[i]), files);
+ for (const auto &f : files) {
+ opt->refFiles.push_back(f);
}
} else {
args.push_back(arg);
std::string cmd = std::string(*it);
it = args.erase(it);
- //sh-3.2# dotnettool --ni-system
+ //sh-3.2# dotnettool --ni-system [AssemblyDirectory] [AssemblyDirectory] ...
if (cmd == "--ni-system") {
- int ret = createNIPlatform(opt);
+ std::string inputs;
+ while (it != args.end()) {
+ const std::string dir = std::string(*it);
+ inputs = inputs + ":" + dir;
+ it = args.erase(it);
+ }
+ int ret = createNIPlatform(inputs, opt);
if (ret != NI_ERROR_NONE) {
_SERR("Failed to generate system NI");
}
if (args.size() < 1) {
_SERR("DLL path is missing");
}
+ std::vector<std::string> inputs;
while (it != args.end()) {
std::string dll = std::string(*it);
+ inputs.push_back(dll);
+ opt->refFiles.push_back(dll);
+ if (opt->flags & NI_FLAGS_INPUT_BUBBLE) {
+ opt->inputBubbleRefFiles.push_back(dll);
+ }
+ it = args.erase(it);
+ }
+
+ for (auto &dll : inputs) {
int ret = createNIDll(dll, opt);
if (ret != NI_ERROR_NONE && ret != NI_ERROR_ALREADY_EXIST) {
_SERR("Failed to generate NI file [%s]", dll.c_str());
break;
}
- it = args.erase(it);
}
}
//sh-3.2# dotnettool --ni-pkg [pkgId] [pkgId] ...
args.push_back(CLRJIT_PATH.c_str());
args.push_back(CROSSGEN_OPT_TARGET_ARCH);
args.push_back(ARCHITECTURE_IDENTIFIER);
- if (!(opt->flags & NI_FLAGS_NO_PIPELINE)) {
- args.push_back(CROSSGEN_OPT_OUT_NEAR_INPUT);
- args.push_back(CROSSGEN_OPT_SINGLE_FILE_COMPILATION);
- }
+
//args.push_back(OPT_PARALLELISM);
//args.push_back(OPT_PARALLELISM_COUNT);
args.push_back(CROSSGEN_OPT_RESILIENT);
args.push_back(CROSSGEN_OPT_INPUTBUBBLE);
args.push_back(CROSSGEN_OPT_COMPILE_BUBBLE_GENERICS);
- if (opt->flags & NI_FLAGS_INPUT_BUBBLE_REF) {
- INPUTBUBBLE_REF_VECTOR.clear();
- // check inputbubbleref format.
- for (const auto &path : opt->inputBubbleRefPath) {
- if (checkDllExistInDir(path)) {
- INPUTBUBBLE_REF_VECTOR.push_back("--inputbubbleref:" + path + "/*.dll");
- }
- }
- // add ref path to inputbubble ref
- for (const auto &path : refPaths) {
- if (checkDllExistInDir(path)) {
- INPUTBUBBLE_REF_VECTOR.push_back("--inputbubbleref:" + path + "/*.dll");
- }
- }
- for (const auto &path : INPUTBUBBLE_REF_VECTOR) {
+ INPUTBUBBLE_REF_VECTOR.clear();
+ for (const auto &path : opt->inputBubbleRefFiles) {
+ INPUTBUBBLE_REF_VECTOR.push_back("--inputbubbleref:" + path);
+ }
+ for (const auto &path : INPUTBUBBLE_REF_VECTOR) {
+ if (find(args.begin(), args.end(), path) == args.end()) {
args.push_back(path.c_str());
}
}
MIBC_VECTOR.push_back("--mibc:" + path);
}
for (const auto &path : MIBC_VECTOR) {
- args.push_back(path.c_str());
+ if (find(args.begin(), args.end(), path) == args.end()) {
+ args.push_back(path.c_str());
+ }
}
}
REF_VECTOR.clear();
// set reference path
- if (opt->flags & NI_FLAGS_REF) {
- for (const auto &path : opt->refPath) {
+ for (const auto &path : opt->refFiles) {
+ REF_VECTOR.push_back("-r:" + path);
+ }
+
+ std::vector<std::string> paths = __pm->getPlatformAssembliesPaths();
+ for (const auto &path : paths) {
+ if (checkDllExistInDir(path)) {
REF_VECTOR.push_back("-r:" + path + "/*.dll");
}
- } else {
- std::vector<std::string> paths = __pm->getPlatformAssembliesPaths();
- for (const auto &path : paths) {
- if (checkDllExistInDir(path)) {
- REF_VECTOR.push_back("-r:" + path + "/*.dll");
- }
- }
}
if (opt->flags & NI_FLAGS_EXTRA_REF) {
}
for (const auto &path : REF_VECTOR) {
- args.push_back(path.c_str());
+ if (find(args.begin(), args.end(), path) == args.end()) {
+ args.push_back(path.c_str());
+ }
}
}
}
static ni_error_e crossgen2PostAction(const std::string& dllPath, const std::string& niPath, NIOption* opt) {
- if (!exist(niPath)) {
- removeFile(changeExtension(niPath, ".ni.dll", ".ni.dll.tmp"));
- _SERR("Fail to create native image for %s", dllPath.c_str());
+ std::string outFile = niPath;
+ if (!exist(outFile)) {
return NI_ERROR_NO_SUCH_FILE;
}
- copySmackAndOwnership(dllPath, niPath);
+ copySmackAndOwnership(dllPath, outFile);
+
// if AppNI then move ni.dll file to .native_image and copy pdb to .native_image
if (opt->flags & NI_FLAGS_APPNI) {
- std::string appNIPath = getAppNIFilePath(dllPath, opt);
- moveFile(niPath, appNIPath);
- makePdbSymlinkForNI(dllPath, appNIPath);
- _SOUT("Native image %s generated successfully.", appNIPath.c_str());
- } else {
- _SOUT("Native image %s generated successfully.", niPath.c_str());
+ outFile = getAppNIFilePath(dllPath, opt);
+ makePdbSymlinkForNI(dllPath, outFile);
+
+ if (opt->flags & NI_FLAGS_INPUT_BUBBLE && opt->flags & NI_FLAGS_NO_PIPELINE) {
+ outFile = outFile + ".tmp";
+ }
+
+ if (niPath != outFile) {
+ moveFile(niPath, outFile);
+ }
+ }
+
+ if (!(opt->flags & NI_FLAGS_INPUT_BUBBLE && opt->flags & NI_FLAGS_NO_PIPELINE)) {
+ _SOUT("Native image %s generated successfully.", outFile.c_str());
}
+
return NI_ERROR_NONE;
}
} else {
std::vector<const char*> argv;
makeArgs(argv, refPaths, opt);
+ argv.push_back(CROSSGEN_OPT_OUT_NEAR_INPUT);
+ argv.push_back(CROSSGEN_OPT_SINGLE_FILE_COMPILATION);
// add input files at the end of parameter
for (const auto &input : dllList) {
} else {
niPath = getNIFilePath(dllPath);
}
-
#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
uintptr_t baseAddr = 0;
if (isTPADll(dllPath)) {
baseAddr = getNextBaseAddr();
}
#endif
+ if (opt->flags & NI_FLAGS_INPUT_BUBBLE) {
+ niPath += ".tmp";
+ }
// fork crossgen2
pid_t pid = fork();
{
std::string coreLib = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.dll");
std::string niCoreLib = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.ni.dll");
+ std::string niTmpCoreLib = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.ni.dll.tmp");
std::string coreLibBackup = concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.dll.Backup");
std::vector<std::string> dllList;
dllList.push_back(getAbsolutePath(coreLib));
if (!isFile(coreLibBackup) && !isR2RImage(coreLib)) {
- if (crossgen2NoPipeLine(dllList, refPaths, opt) == NI_ERROR_NONE && exist(niCoreLib)) {
+ if (crossgen2NoPipeLine(dllList, refPaths, opt) == NI_ERROR_NONE) {
if (rename(coreLib.c_str(), coreLibBackup.c_str())) {
- _SERR("Failed to rename System.Private.CoreLib.dll");
+ _SERR("Failed to rename from System.Private.CoreLib.dll to System.Private.CoreLib.dll.Backup");
return NI_ERROR_CORE_NI_FILE;
}
- if (rename(niCoreLib.c_str(), coreLib.c_str())) {
- _SERR("Failed to rename System.Private.CoreLib.ni.dll");
- return NI_ERROR_CORE_NI_FILE;
+ if (opt->flags & NI_FLAGS_INPUT_BUBBLE) {
+ if (rename(niTmpCoreLib.c_str(), coreLib.c_str())) {
+ _SERR("Failed to rename from System.Private.CoreLib.ni.dll.tmp to Private.CoreLib.dll");
+ return NI_ERROR_CORE_NI_FILE;
+ }
+ } else {
+ if (rename(niCoreLib.c_str(), coreLib.c_str())) {
+ _SERR("Failed to rename from System.Private.CoreLib.ni.dll to Private.CoreLib.dll");
+ return NI_ERROR_CORE_NI_FILE;
+ }
}
} else {
_SERR("Failed to create native image for %s", coreLib.c_str());
if (opt->flags & NI_FLAGS_NO_PIPELINE) {
ret = crossgen2NoPipeLine(dllList, paths, opt);
} else {
- // When the forked process in the pipeline state is terminated(WIFSIGNALED(status)),
- // retry the generation of the native image
- // if the number of .dll files and the number of .ni.dll files are different.
- for (int callCnt = 0; callCnt < 2; callCnt++) {
- // If an error occurs, perform it twice with the same option.
- ret = crossgen2PipeLine(dllList, paths, opt);
- if (ret != NI_ERROR_NONE) {
- _SERR("Crossgen2 is abnormally terminated. Regenerate native images that failed while running crossgen2.");
- dllList.clear();
- for (auto it = niList.begin(); it != niList.end(); it++) {
- std::string niPath = *it;
- std::string dllPath = changeExtension(niPath, ".ni.dll", ".dll");
- if (crossgen2PostAction(dllPath, niPath, opt) != NI_ERROR_NONE) {
- dllList.push_back(dllPath);
- } else {
- niList.erase(it--);
- }
+ std::vector<std::string> notCompiled;
+ ret = crossgen2PipeLine(dllList, paths, opt);
+ if (ret != NI_ERROR_NONE) {
+ _SERR("Crossgen2 is abnormally terminated. Regenerate native images that failed while running crossgen2.");
+ for (auto &dll : dllList) {
+ std::string tFile = changeExtension(dll, ".dll", ".ni.dll");
+ if (opt->flags & NI_FLAGS_INPUT_BUBBLE) {
+ tFile += ".tmp";
+ }
+ if (!exist(tFile)) {
+ notCompiled.push_back(dll);
}
- } else {
- break;
}
- }
- // If an error occurs after two crossgen2PipeLine() attempts,
- // try crossgen2NoPipeLine() for the last time.
- if (ret != NI_ERROR_NONE) {
_SERR("Retry running crossgen2 with --no-pipeline mode to avoid termination by OOM.");
- ret = crossgen2NoPipeLine(dllList, paths, opt);
+ ret = crossgen2NoPipeLine(notCompiled, paths, opt);
+ }
+ }
+
+ if (ret == NI_ERROR_NONE && opt->flags & NI_FLAGS_INPUT_BUBBLE) {
+ for (auto &dll : dllList) {
+ std::string tmpFile;
+ std::string niFile;
+ if (opt->flags & NI_FLAGS_APPNI) {
+ niFile = getAppNIFilePath(dll, opt);
+ } else {
+ niFile = getNIFilePath(dll);
+ }
+ tmpFile = niFile + ".tmp";
+
+ if (exist(tmpFile)) {
+ moveFile(tmpFile, niFile);
+ _SOUT("Native image %s generated successfully.", niFile.c_str());
+ }
}
}
}
}
-ni_error_e createNIPlatform(NIOption* opt)
+ni_error_e createNIPlatform(std::string& extraInputs, NIOption* opt)
{
- ni_error_e ret = createNIUnderDirs(__pm->getRuntimePath(), opt);
- if (ret != NI_ERROR_NONE) {
- return ret;
- }
+ extraInputs += ":" + __pm->getRuntimePath();
+ extraInputs += ":" + __pm->getTizenFXPath();
- return createNIUnderDirs(__pm->getTizenFXPath(), opt);
+ return createNIUnderDirs(extraInputs, opt);
}
ni_error_e createNIDll(const std::string& dllPath, NIOption* opt)
{
ni_error_e ret;
+ bool isAppNI = false;
+ if (opt->flags & NI_FLAGS_APPNI) {
+ isAppNI = true;
+ }
+
+ if (opt->flags & NI_FLAGS_INPUT_BUBBLE) {
+ std::vector<std::string> refs;
+ splitPath(refPaths, refs);
+ for (auto &p: refs) {
+ if (isDirectory(p) && checkDllExistInDir(p)) {
+ opt->inputBubbleRefFiles.push_back(p + "/*.dll");
+ }
+ }
+ }
+
// get managed file list from targetPath
std::vector<std::string> dllList;
ret = getTargetDllList(targetPath, dllList);
// So, unset NI_FLAGS_APPNI temporally and restore it after running AOT.
opt->flags &= ~NI_FLAGS_APPNI;
ret = doAOTList(needNIList, refPaths, opt);
- opt->flags |= NI_FLAGS_APPNI;
+ if (isAppNI) {
+ opt->flags |= NI_FLAGS_APPNI;
+ }
if (ret != NI_ERROR_NONE) {
return ret;
}
}
- for (auto &niPath : niList) {
- if (exist(niPath)) {
- std::string symNIPath = concatPath(targetPath, getFileName(niPath));
- if (!exist(symNIPath)) {
- bf::create_symlink(niPath, symNIPath);
- copySmackAndOwnership(targetPath.c_str(), symNIPath.c_str(), true);
- _SOUT("%s symbolic link file generated successfully.", symNIPath.c_str());
- _INFO("%s symbolic link file generated successfully.", symNIPath.c_str());
+ if (isAppNI) {
+ for (auto &niPath : niList) {
+ if (exist(niPath)) {
+ std::string symNIPath = concatPath(targetPath, getFileName(niPath));
+ if (!exist(symNIPath)) {
+ bf::create_symlink(niPath, symNIPath);
+ copySmackAndOwnership(targetPath.c_str(), symNIPath.c_str(), true);
+ _SOUT("%s symbolic link file generated successfully.", symNIPath.c_str());
+ _INFO("%s symbolic link file generated successfully.", symNIPath.c_str());
+ }
}
}
}
std::vector<std::string> paths;
splitPath(rootPaths, paths);
+ if (opt->flags & NI_FLAGS_INPUT_BUBBLE) {
+ for (auto &p: paths) {
+ if (isDirectory(p) && checkDllExistInDir(p)) {
+ opt->inputBubbleRefFiles.push_back(p + "/*.dll");
+ }
+ }
+ }
+
for (const auto &path : paths) {
if (!exist(path)) {
continue;