@ -58,11 +58,9 @@ bool CMake::update_default_build(const boost::filesystem::path &default_build_pa
}
}
}
}
if ( ! force & & boost : : filesystem : : exists ( default_build_path / " compile_commands.json " , ec ) )
if ( ! create_file_api_query ( default_build_path ) & & ! force & & boost : : filesystem : : exists ( default_build_path / " compile_commands.json " , ec ) )
return true ;
return true ;
set_file_api_queries ( default_build_path ) ;
auto compile_commands_path = default_build_path / " compile_commands.json " ;
auto compile_commands_path = default_build_path / " compile_commands.json " ;
bool canceled = false ;
bool canceled = false ;
Dialog : : Message message ( " Creating/updating default build " , [ & canceled ] {
Dialog : : Message message ( " Creating/updating default build " , [ & canceled ] {
@ -124,8 +122,6 @@ bool CMake::update_debug_build(const boost::filesystem::path &debug_build_path,
if ( ! force & & boost : : filesystem : : exists ( debug_build_path / " CMakeCache.txt " , ec ) )
if ( ! force & & boost : : filesystem : : exists ( debug_build_path / " CMakeCache.txt " , ec ) )
return true ;
return true ;
set_file_api_queries ( debug_build_path ) ;
bool canceled = false ;
bool canceled = false ;
Dialog : : Message message ( " Creating/updating debug build " , [ & canceled ] {
Dialog : : Message message ( " Creating/updating debug build " , [ & canceled ] {
canceled = true ;
canceled = true ;
@ -152,11 +148,10 @@ bool CMake::update_debug_build(const boost::filesystem::path &debug_build_path,
boost : : filesystem : : path CMake : : get_executable ( const boost : : filesystem : : path & build_path , const boost : : filesystem : : path & file_path ) {
boost : : filesystem : : path CMake : : get_executable ( const boost : : filesystem : : path & build_path , const boost : : filesystem : : path & file_path ) {
// prefer the CMake file API (if available) which gives exact information about the targets a file belongs to
// Prefer the CMake file API (if available) which gives exact information about the targets a file belongs to
auto executables = get_executables ( build_path , file_path ) ;
auto executable = get_executable_from_file_api ( build_path , file_path ) ;
if ( ! executables . empty ( ) ) {
if ( executable )
return executables . front ( ) ;
return * executable ;
}
// CMake does not store in compile_commands.json if an object is part of an executable or not.
// CMake does not store in compile_commands.json if an object is part of an executable or not.
// Therefore, executables are first attempted found in the cmake files. These executables
// Therefore, executables are first attempted found in the cmake files. These executables
@ -363,67 +358,84 @@ void CMake::parse_file(const std::string &src, std::map<std::string, std::list<s
}
}
}
}
void CMake : : set_file_api_queries ( const boost : : filesystem : : path & build_path ) {
bool CMake : : create_file_api_query ( const boost : : filesystem : : path & build_path ) {
auto query_directory = build_path / " .cmake " / " api " / " v1 " / " query " / " client-jucipp " ;
auto query_directory = build_path / " .cmake " / " api " / " v1 " / " query " / " client-jucipp " ;
auto query_file = query_directory / " query.json " ;
boost : : system : : error_code ec ;
boost : : system : : error_code ec ;
if ( ! boost : : filesystem : : exists ( query_directory , ec ) ) {
if ( boost : : filesystem : : exists ( query_file , ec ) )
boost : : system : : error_code ec ;
return false ;
boost : : filesystem : : create_directories ( query_directory , ec ) ;
boost : : filesystem : : create_directories ( query_directory , ec ) ;
if ( ec ) {
if ( ec ) {
Terminal : : get ( ) . print ( " \ e[31mError \ e[m: could not create " + filesystem : : get_short_path ( query_directory ) . string ( ) + " : " + ec . message ( ) + " \n " , true ) ;
Terminal : : get ( ) . print ( " \ e[31mError \ e[m: could not create cmake file api query directory " + filesystem : : get_short_path ( query_directory ) . string ( ) + " : " + ec . message ( ) + " \n " , true ) ;
return ;
return false ;
}
}
}
filesystem : : write ( query_directory / " query.json " , R " ({
if ( ! filesystem : : write ( query_file , R " ({
" requests " : [
" requests " : [
{ " kind " : " codemodel " , " version " : 2 }
{ " kind " : " codemodel " , " version " : 2 }
]
]
} ) " );
} ) " )) {
Terminal : : get ( ) . print ( " \ e[31mError \ e[m: could not create cmake file api query file " + filesystem : : get_short_path ( query_file ) . string ( ) + " : " + ec . message ( ) + " \n " , true ) ;
return false ;
}
return true ;
}
}
std : : vector < boost : : filesystem : : path > CMake : : get_executables ( const boost : : filesystem : : path & build_path , const boost : : filesystem : : path & file_path ) {
boo st: : optional < boost : : filesystem : : path > CMake : : get_executable_from_file_api ( const boost : : filesystem : : path & build_path , const boost : : filesystem : : path & file_path ) {
auto reply_directory = build_path / " .cmake " / " api " / " v1 " / " reply " ;
auto reply_directory = build_path / " .cmake " / " api " / " v1 " / " reply " ;
boost : : system : : error_code ec ;
boost : : system : : error_code ec ;
if ( ! boost : : filesystem : : exists ( reply_directory , ec ) ) {
if ( ! boost : : filesystem : : is_directory ( reply_directory , ec ) ) {
// If the reply directory does not exist, either CMake was not run or the file API is not yet supported
// If the reply directory does not exist, either CMake was not run or the file API is not yet supported
return { } ;
return { } ;
}
}
// check all target-*.json files and filter for the given file path
// Check all target-*.json files and filter for the given file path
std : : vector < boost : : filesystem : : path > executables ;
std : : vector < boost : : filesystem : : path > target_files ;
for ( const auto & reply_file : boost : : filesystem : : directory_iterator ( reply_directory ) ) {
for ( const auto & reply_file : boost : : filesystem : : directory_iterator ( reply_directory , ec ) ) {
if ( reply_file . path ( ) . stem ( ) . string ( ) . find ( " target- " ) ! = 0 ) {
auto reply_file_path = reply_file . path ( ) ;
continue ;
if ( starts_with ( reply_file_path . stem ( ) . string ( ) , " target- " ) )
target_files . emplace_back ( reply_file_path ) ;
}
}
std : : sort ( target_files . begin ( ) , target_files . end ( ) , [ ] ( const boost : : filesystem : : path & path1 , const boost : : filesystem : : path & path2 ) {
return Natural : : compare ( path1 . string ( ) , path2 . string ( ) ) < 0 ;
} ) ;
JSON json { reply_file . path ( ) } ;
boost : : optional < boost : : filesystem : : path > executable ;
auto artifacts = json . array_optional ( " artifacts " ) ;
ssize_t best_match_size = - 1 ;
if ( ! artifacts | | artifacts - > empty ( ) ) {
for ( const auto & target_file : target_files ) {
continue ;
try {
}
JSON json ( target_file ) ;
auto relative_path = artifacts - > front ( ) . string_optional ( " path " ) ;
if ( ! relative_path ) {
continue ;
}
auto type = json . string_optional ( " type " ) ;
if ( json . string ( " type " ) ! = " EXECUTABLE " )
if ( ! type | | * type ! = " EXECUTABLE " ) {
continue ;
continue ;
}
auto source s = json . array_optional ( " source s" ) ;
auto artifact s = json . array ( " artifact s" ) ;
if ( ! sources ) {
if ( artifacts . empty ( ) )
continue ;
continue ;
auto relative_path = artifacts . front ( ) . string ( " path " ) ;
for ( auto & source : json . array ( " sources " ) ) {
auto source_file = project_path / source . string ( " path " ) ;
if ( source_file = = file_path )
return { build_path / relative_path } ;
auto source_directory = source_file . parent_path ( ) ;
if ( filesystem : : file_in_path ( file_path , source_directory ) ) {
auto size = std : : distance ( source_directory . begin ( ) , source_directory . end ( ) ) ;
if ( size > best_match_size ) {
best_match_size = size ;
executable = build_path / relative_path ;
}
}
for ( const auto & source : * sources ) {
auto source_path = project_path / source . string_or ( " path " , " " ) ;
if ( source_path = = file_path ) {
executables . emplace_back ( build_path / * relative_path ) ;
}
}
}
}
}
}
return executables ;
catch ( . . . ) {
}
}
return executable ;
}
}