Per-source cflags - node-gyp

Is there a way in gyp to enable certain cflags only for some source files?
In the context of this bug I'd like to find a way to have some code compiled with some SSE features enabled, while other code (to detect the availability of said features at runtime and to offer fallbacks) should not make use of those features during optimization.
As so often, I find the node-gyp documentation thoroughly insufficient.

As workaround you can create a static library target in your .GYP file with specific cflags and then to link this static lib against your main target depending on some condition.
{
'variables: {
'use_sse4%': 0, # may be redefined in command line on configuration stage
},
'targets: [
# SSE4 specific target
{
'target_name': 'sse4_arch',
'type': 'static_library',
'sources': ['sse4_code.cpp'],
'cflags': ['-msse4.2'],
},
# Non SSE4 code
{
'target_name': 'generic_arch',
'type': 'static_library',
'sources': ['generic_code.cpp'],
},
# Your main target
{
'target_name': 'main_target',
'conditions': [
['use_sse4==1', # conditional dependency on the `use_ss4` variable
{ 'dependencies': ['sse4_arch'] }, # true branch
{ 'dependencies': ['generic_arch'] } # false branch
],
],
},
],
}
More details on dependencies, variables, and conditions are in GYP documentation

Related

VS Code Mac m1 Debug is not hitting my breakpoints with Makefile conf C language

Hello !
I'm new with using VS Code while programming in C language and I'm trying to debug my program with the "Makefile Tools" plugin but it doesn't seem to consider any of my breakpoints.
Config/Environment:
Mac M1 2021, MacOS Monterey
C programming language
Makefile compilation (GCC)
Run: ./binary test_file
Here are the steps I've done:
First I downloaded C/C++ IntelliSense and Makefile Tools for VS Code.
Then I configured it using the documentation, as follow:
{
"makefile.extensionOutputFolder": "./.vscode",
"makefile.configurations": [
{
"name": "Default",
"makeArgs": []
},
],
"makefile.launchConfigurations": [
{
"cwd": "/Path/to/workdir",
"binaryPath": "/Path/to/binary",
"binaryArgs": [
"/Path/to/test_file"
]
}
],
"C_Cpp.default.configurationProvider": "ms-vscode.makefile-tools"
}
I selected in the tree my binary and rules:
like this
Finally I build then run and my breakpoint doesn't get hit.
Maybe some clues can be found in this log, I'm not sure:
2022-05-06 15:04:22.645419+0200 fdf[99469:2207846] [default] error finding potential wrapper bundle for node <FSNode 0x60000021c0a0> { isDir = ?, path = '/Users/julian/Documents/42/fdf' }: Error Domain=NSOSStatusErrorDomain Code=-10811 "kLSNotAnApplicationErr: Item needs to be an application, but is not" UserInfo={_LSLine=1579, _LSFunction=wrapperBundleNodeForWrappedNode}
But I've found nothing about it on the internet.
Can someone help me with using the debug mode in VS Code ?
Are you compiling with -g flag in your Makefile?

How do you handle include dependencies passed as #defines in Bazel?

I am attempting to build a legacy C/C++ embedded code base using Bazel. The code is separated into software sets. Because the system is embedded, there is an environment header include passed as an argument to the compiler for each software set. The header path is defined using a #define:
The source file of software_set_b may begin with:
#include MY_ENV
The compile instruction would define MY_ENV to the absolute path of the environment header in software_set_a, e.g.:
gcc -DMY_ENV=/path/to/software_set_a/headers/MyEnvironmentHeader.h
Is it possible to achieve this using Bazel without explicitly passing /path/to/software_set_a/headers/MyEnvironment.h in the --define argument in bazel build, or hardcoding the value in software_set_b's BUILD file, e.g.:
cc_library(
name = 'software_set_b',
defines = [
'MY_ENV=/path/to/software_set_a/headers/MyEnvironment.h'
],
...
)
Ideally, the programmer could select the package with an argument, e.g. bazel build //:software_set_b --//:from_env=software_set_a with a fragment similar to the following in the BUILD script:
File: software_set_b/BUILD
string_flag(
name = 'from_env',
build_setting_default = ''
)
def deps_from_env():
from_env = get_flag_value('from_env') # A function that gets the value of the flag.
return '#' + from_env + '//:env' # Evaluate to e.g. '#software_set_a//:env'
cc_library(
name = 'software_set_b',
deps = [
deps_from_env()
]
)
File: software_set_a/BUILD
cc_library(
name = 'env',
defines = [
# Something to give me '/path/to/software_set_a/headers/MyEnvironment.h'
'MY_ENV=$(rootpath)/headers/MyEnvironment.h'
],
...
)
This is relatively simple to do e.g. Create an env target under both software_set_a and software_set_b.
# File: //software_set_a:BUILD
cc_library(
name = 'env',
defines = [
'MY_ENV=$(rootpath)/headers/MyEnvironment.h'
],
)
cc_library(
name = 'software_set_a',
deps = [
# Top level switchable target. NOTE: This is NOT ":env".
"//:from_env",
]
)
# File: //software_set_b:BUILD
cc_library(
name = 'env',
defines = [
'MY_ENV=$(rootpath)/headers/MyEnvironment.h'
],
)
cc_library(
name = 'software_set_b',
deps = [
# Top level switchable target. NOTE: This is NOT ":env".
"//:from_env",
]
)
Now of course by itself this won't work. So we need to create a switchable top level env target.
# //:BUILD
label_flag(
name = "from_env",
build_setting_default = "//software_set_b:env",
)
Now by default the env defines will be pulled from software set b. But can be overridden with the command.
bazel build //:software_set_b --//:from_env=software_set_a:env
Note that you can have an empty default by simply creating a cc_library(name="empty") and pointing the default_build_setting at that. Further, you might find the pattern of configuration around constraint_setting/constraint_value/platform/select to be a more useful pattern for you, rather than your flag based approach. Also note that you can combine the two by pointing the label flag at a selectable multiplexer target. A more advanced example can be found in bazelembedded/rules_cc_toolchain under the files;
config/rules_cc_toolchain_config.BUILD
config/BUILD.bazel

VSCode C trouble: Debug and Build C on Windows

I'm trying to setup VSCode to build and debug C on Windows.
I have installed MinGW.
I'm trying to generate an .exe file for the following code:
#define USE_PTS true
#include "Cartography.h"
static Cartography cartography ;
static int nCartography = 0;
int main(void)
{
nCartography = loadCartography("map (1).txt", &cartography);
showCartography(cartography, nCartography);
interpreter(cartography, nCartography);
return 0;
}
I have two other files Cartography.hand Cartography.c.
If I run the following command using the powershell terminal, it generates an .exe file perfectly:
gcc -std=c11 -o Main Cartography.c Main.c -lm
But if I try to build it using VSCode (using Ctrl + Shift + B) it doesn't recognize the other files:
> Executing task in folder Projeto2LAP: gcc -std=c11 -o Main Cartography.c Main.c -lm <
gcc.exe: error: Cartography.c: No such file or directory
gcc.exe: error: Main.c: No such file or directory
The terminal process terminated with exit code: 1
Terminal will be reused by tasks, press any key to close it.
Here is my tasks.json file:
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "C/C++: gcc.exe build active file",
"command": "gcc -std=c11 -o Main Cartography.c Main.c -lm",
"options": {
"cwd": "C:\\Program Files (x86)\\mingw-w64\\i686-8.1.0-posix-dwarf-rt_v6-rev0\\mingw32\\bin"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
The other issue I have is when I'm trying to use the built in VSCode debugger.
I generate the .exe file using the command I mentioned, so an .exe file is present in the current folder.
(I should also mention that the folder I'm working on only contains the files and the .vscode folder, there are no subfolders or anything that could cause an error).
When I click on debug it gives me the following error message:
Error message prompt
Here is my launch.json file:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/Main.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "C:/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/bin/gdb.exe",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}
What am I doing wrong?
Your first question:
When you use the powershell command, it gets your *.c files from your current wording directory via relative paths. This is what you attempt to do in the task command, but your CWD is set to the wrong place. In tasks.json, you need to either specify the absolute paths of your files in the gcc command or change your CWD to the directory of the *.c files. Or better, VSC lets you set "cwd": "${workspaceFolder}". This means if you change the name or do any other edits, your task will still work. (For bonus points, you could set the CWD to the enclosing folder of the currently selected file.) First question part 2: The task error probably isn't you. It appears to be a known bug. Instructions here to mitigate it.
Sorry for the late response
I don't see any reason why you would get the debugging error, so my only guess is a permissions problem. Your debugger may not be able to "see" that that directory exists. Make sure neither it nor any of its parent folders have unduly tights restrictions.
Rather than pass one long string to launch GCC in tasks.json, consider using the "args" list variable, placing each arg in a separate element of the list.
Assuming your source files are located within the same directory that was opened in VSCode, the previously-mentioned "${workspaceFolder}" macro will construct the correct paths.
Otherwise, provide absolute paths to your source files as earlier suggested.
Example:
{
"label": "GCC Build Debug (64-bit)",
"type": "shell",
"command": "C:\\Program Files (x86)\\mingw-w64\\i686-8.1.0-posix-dwarf-rt_v6-rev0\\mingw32\\bin\\gcc",
"args": [
"--std=c11",
"-g",
"-lm",
"-o",
"${workspaceFolder}/Main"
"${workspaceFolder}/Main.c",
"${workspaceFolder}/Cartography.c"
],
"problemMatcher": [
"$msCompile"
]
},

Visual Studio Code Task to Compile and Run .c Files

How can I create a task in Visual Studio Code (the most recent version) to compile and run .c files.
I found this online:
"version": "2.0.0",
"tasks": [
{
"label": "compile and run C",
"type": "shell",
"command": "(gcc -g ${file} -o ${fileBasenameNoExtension}) -and (./${fileBasenameNoExtension})",
"presentation": {
"reveal": "always",
"panel": "shared"
},
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
I managed to tweak it but it still wont compile and run at the same time, instead I get this:
> Executing task: (gcc -g d:\ISEP\ARQCP\partilha\arqcp19202deg01\pl0_7.c -o pl0_7) -and (./pl0_7) <
False
Terminal will be reused by tasks, press any key to close it.
Is there any way to compile and run my code with a simple shortcut (currently i press CTRL+SHIFT+B to "compile and run")?
So I kept looking for a way to do it and I found this simple extension: Code Runner.
Basically it just adds a Run Code button for most of the coding languages and it makes it so much easier.

Gradle: How to designate a output directory for C/C++ object files?

I have a fairly simple build.gradle file which builds a zlib directory. Unfortunately, the resulting *.o file are sprinkled into individual directories. e.g.
build/objs/zlib/shared/zlibC/xvtb7xzcn488esep2yp1v714/uncompr.o
build/objs/zlib/shared/zlibC/2osjpf8p443huii37rw8g7o7d/zutil.o
[...]
build/objs/zlib/shared/zlibC/bkho3m4h5simvpsegapx51g54/trees.o
build/objs/zlib/shared/zlibC/2zicemubjlmw82yi1ysriaup4/inflate.o
How do you set the output directory to be build/zlib for all the resulting *.o files (minus the unique-id directories)?
apply plugin: 'c'
FileCollection zlibfiles = files(
'adler32',
[...]
'trees',
'zutil')
model {
components {
zlib(NativeLibrarySpec) {
sources {
c {
source {
srcDir "."
include '*.c'
}
exportedHeaders {
srcDir '.'
}
}
}
}
}
binaries {
withType(SharedLibraryBinarySpec) {
if (targetPlatform.operatingSystem.linux) {
cppCompiler.args '-c', '-g', '-fPIC'
// relative paths are ignored by Gradle
// only fully qualified paths are recognized
// cppCompiler.args '-I', '../..'
cppCompiler.args '-I', "${rootDir}/zlib"
linker.args '-pthread'
}
}
}
}
I have a find-copy task, but the goal here is use Gradle properly. I would rather use Gradle's version of gcc/g++ '-o' option.
task zlibcopy (type: Copy) {
configurations {
conf
}
dependencies {
conf fileTree(dir: "${buildDir}/objs/zlib/shared/zlibC/")
}
from configurations.conf.getAsFileTree()
into "${rootDir}/build/client/ps/common/zlib"
}
Gradle: 4.7
CentOS: 7.4
Java: 1.8.0_144
Apparently, Gradle does not allow native code to be outputted to a designated output directory. You can find the *.o's in uniquely identified output directories, the *.so in a "shared" directory, and *.a in a "static" directory. Darn.
Try that, the unique directories won't be included.
task zlibcopy (type: Copy) {
zlibfiles.each { File file ->
println file.name
from ("${buildDir}/objs/zlib/shared/zlibC/") {
include "**/${file.name}*"
}
includeEmptyDirs = false
eachFile {
def (id, name) = it.path.split('/')
it.relativePath = RelativePath.parse(true, name)
}
into "${rootDir}/build/zlib"
}
}
the last six *.o files are never copied
Maybe these six files are not included in zlibfiles and by consequence, never included ?

Resources