I'm trying to run this example utilizing Crypto++library, and I downloaded/stored Crypto++ in /home/thirdparty/cryptopp. However, when run the following command line:
g++ -I/home/thirdParty channelSwitch.cpp -L/home/thirParty -o test-cs.exe
Can someone help check what is the problem?
/tmp/ccPnCG56.o: In function `main':
channelSwitch.cpp:(.text+0x178): undefined reference to `CryptoPP::StringSinkTemplate<std::string>::StringSinkTemplate(std::string&)'
channelSwitch.cpp:(.text+0x21b): undefined reference to `CryptoPP::DEFAULT_CHANNEL'
channelSwitch.cpp:(.text+0x221): undefined reference to `CryptoPP::DEFAULT_CHANNEL'
channelSwitch.cpp:(.text+0x237): undefined reference to `CryptoPP::HashFilter::HashFilter(CryptoPP::HashTransformation&, CryptoPP::BufferedTransformation*, bool, int, std::string const&, std::string const&)'
channelSwitch.cpp:(.text+0x292): undefined reference to `CryptoPP::StringSinkTemplate<std::string>::StringSinkTemplate(std::string&)'
channelSwitch.cpp:(.text+0x31d): undefined reference to `CryptoPP::DEFAULT_CHANNEL'
channelSwitch.cpp:(.text+0x323): undefined reference to `CryptoPP::DEFAULT_CHANNEL'
channelSwitch.cpp:(.text+0x339): undefined reference to `CryptoPP::HashFilter::HashFilter(CryptoPP::HashTransformation&, CryptoPP::BufferedTransformation*, bool, int, std::string const&, std::string const&)'
...
collect2: error: ld returned 1 exit status
The complete source code for channelSwitch.cpp is:
#include <iostream>
#include <cstring>
#include <cryptopp/channels.h>
#include <cryptopp/filters.h>
#include <cryptopp/sha.h>
#include <cryptopp/hex.h>
int main(int argc, char *argv[]) {
std::string message = "Now is the time for all good men to come to the aide of their country";
// Allow user to override default message from command line arg.
if(argc == 2 && argv[1] != NULL)
message = std::string(argv[1]);
// Set hash variables
std::string s1, s2, s3, s4;
CryptoPP::SHA1 sha1; CryptoPP::SHA224 sha224; CryptoPP::SHA256 sha256; CryptoPP::SHA512 sha512;
// Run hash functions
CryptoPP::HashFilter f1(sha1, new CryptoPP::HexEncoder(new CryptoPP::StringSink(s1)));
CryptoPP::HashFilter f2(sha224, new CryptoPP::HexEncoder(new CryptoPP::StringSink(s2)));
CryptoPP::HashFilter f3(sha256, new CryptoPP::HexEncoder(new CryptoPP::StringSink(s3)));
CryptoPP::HashFilter f4(sha512, new CryptoPP::HexEncoder(new CryptoPP::StringSink(s4)));
// Set route to default
CryptoPP::ChannelSwitch cs;
cs.AddDefaultRoute(f1);
cs.AddDefaultRoute(f2);
cs.AddDefaultRoute(f3);
cs.AddDefaultRoute(f4);
CryptoPP::StringSource ss(message, true /*pumpAll*/, new CryptoPP::Redirector(cs));
std::cout << "Message: " << message << std::endl;
std::cout << "SHA-1: " << s1 << std::endl;
std::cout << "SHA-224: " << s2 << std::endl;
std::cout << "SHA-256: " << s3 << std::endl;
std::cout << "SHA-512: " << s4 << std::endl;
return 0;
}
Environment information:
$ gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
I know what the problem is. should make install first. Thanks!
Related
System information:
OS Platform and Distribution: Linux Ubuntu 18.04
TensorFlow installed source: source
TensorFlow version: 2.2.0 stable
Python version: python3
Bazel version: using Bazelisk with Bazel 2.0.0 version as required
from tf-2.2.0
GCC/Compiler version (if compiling from source): GCC-8
CUDA/cuDNN version: No CUDA (for the moment)
What I have done:
Got tensorflow from github:
git clone --recurse-submodules https://github.com/tensorflow/tensorflow.git
cd tensorflow
git checkout v2.2.0
Installed and setted up Bazelisk: ( Using this guide: https://gist.github.com/philwo/f3a8144e46168f23e40f291ffe92e63c )
$ sudo curl -Lo /usr/local/bin/bazel https://github.com/bazelbuild/bazelisk/releases/download/v1.1.0/bazelisk-linux-amd64
$ sudo chmod +x /usr/local/bin/bazel
$ grep -r _TF_MAX_BAZEL_VERSION .
./configure.py:_TF_MAX_BAZEL_VERSION = '2.0.0'
$ echo '2.0.0' > .bazelversion
$ bazel version
Start building tensorflow with Bazel:
$ ./configure
bazel --host_jvm_args=-Xmx30G build --jobs=8 --config=monolithic --config=v2 --config=opt --copt=-O3 --copt=-march=native --copt=-m64 --verbose_failures //tensorflow:tensorflow //tensorflow:tensorflow_cc //tensorflow:tensorflow_framework //tensorflow/tools/lib_package:libtensorflow
Then with the code:
#include <stdlib.h>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include "class_name.h"
#include "tensorflow/cc/ops/const_op.h"
#include "tensorflow/cc/ops/standard_ops.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/graph/default_device.h"
#include "tensorflow/core/graph/graph_def_builder.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/core/stringpiece.h"
#include "tensorflow/core/lib/core/threadpool.h"
#include "tensorflow/core/lib/io/path.h"
#include "tensorflow/core/lib/strings/stringprintf.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/init_main.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/public/session.h"
#include "tensorflow/core/util/command_line_flags.h"
using namespace tensorflow;
using tensorflow::Flag;
using tensorflow::Status;
using tensorflow::string;
using tensorflow::Tensor;
//Read the image file, apply appropriate decoding depending on type of image
int TensorFromFile(string filename, const int i_height, const int i_width, std::vector<Tensor>* o_tensors) {
tensorflow::Status status;
auto root = tensorflow::Scope::NewRootScope();
using namespace ::tensorflow::ops;
std::unique_ptr<tensorflow::Session> session(tensorflow::NewSession({}));
tensorflow::GraphDef graph;
auto reader = tensorflow::ops::ReadFile(root.WithOpName("img_reader"), filename);
const int channels = 1;
tensorflow::Output imgreader;
if (tensorflow::str_util::EndsWith(filename, ".png")) {
imgreader = DecodePng(root.WithOpName("png_reader"), reader, DecodePng::Channels(channels));
} else if (tensorflow::str_util::EndsWith(filename, ".gif")) {
imgreader = DecodeGif(root.WithOpName("gif_reader"), reader);
} else {
imgreader = DecodeJpeg(root.WithOpName("jpeg_reader"), reader, DecodeJpeg::Channels(channels));
}
auto f_caster = Cast(root.WithOpName("float_caster"), imgreader, tensorflow::DT_FLOAT);
ExpandDims(root.WithOpName("output"), f_caster, 0);
status = root.ToGraphDef(&graph);
if (!status.ok()) {
LOG(ERROR) << status.ToString();
return -1;
}
status = session->Create(graph);
if (!status.ok()) {
LOG(ERROR) << status.ToString();
return -1;
}
status = session->Run({}, {"output"}, {}, o_tensors);
if (!status.ok()) {
LOG(ERROR) << status.ToString();
return -1;
}
return 0;
}
int main(int argc, char* argv[]) {
using namespace ::tensorflow::ops;
tensorflow::Status status;
std::string delimiter = ".";
std::string ofilename;
std::vector<Tensor> inputs;
std::vector<Tensor> outputs;
std::string graph_path = "../../graphs/test0/";
std::string image_path = "../../graphs/test0.png";
std::string mdlpath(graph_path);
std::string imgpath(image_path);
int32 inputdim = 32;
std::unique_ptr<tensorflow::Session> session(tensorflow::NewSession({}));
tensorflow::GraphDef graph;
//read model file
status = ReadBinaryProto(Env::Default(), mdlpath, &graph);
if (!status.ok()) {
std::cout << status.ToString() << "\n";
return -1;
}
//add graph to scope
status = session->Create(graph);
if (!status.ok()) {
std::cout << status.ToString() << "\n";
return -1;
}
//Read input image, assuming to be a sqaure image
if (TensorFromFile(imgpath, inputdim, inputdim, &inputs)) {
LOG(ERROR) << "Image reading failed"
<< "\n";
return -1;
}
LOG(INFO) << "OK";
std::cout << "input dimension of the image: " << inputs[0].DebugString() << std::endl;
//get the appropriate input and out layer names from the graph/mode to execute
auto inputlayer = graph.node(0).name();
auto outputlayer = graph.node(graph.node_size() - 1).name();
status = session->Run({{inputlayer, inputs[0]}}, {outputlayer}, {}, &outputs);
if (!status.ok()) {
LOG(ERROR) << status.ToString();
return -1;
}
std::cout << "Output dimension of the image" << outputs[0].DebugString() << std::endl;
//create filename
ofilename.append(imgpath.substr(0, imgpath.find(delimiter)));
ofilename.append("_mask.png");
std::cout << "output filename: " << ofilename << std::endl;
//Now write this to a image file
//if (TensorToFile(ofilename, outputs, threshold)) return -1;
session->Close();
return 0;
}
I tried to compile with:
f I use theese flags:
g++ -O3 -m64 -o test -I /opt/tpt/tensorflow_cpp_scratch/include/tensorflow/bazel-bin main.cpp -L /opt/tpt/tensorflow_cpp_scratch/lib -l tensorflow_cc
and I got the error:
/tmp/cc4xzZGr.o: In function `google::protobuf::RepeatedPtrField<tensorflow::NodeDef>::TypeHandler::WeakType const& google::protobuf::internal::RepeatedPtrFieldBase::Get<google::protobuf::RepeatedPtrField<tensorflow::NodeDef>::TypeHandler>(int) const':
main.cpp:(.text._ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi[_ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi]+0x6a): undefined reference to `google::protobuf::internal::LogMessage::LogMessage(google::protobuf::LogLevel, char const*, int)'
main.cpp:(.text._ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi[_ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi]+0x79): undefined reference to `google::protobuf::internal::LogMessage::operator<<(char const*)'
main.cpp:(.text._ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi[_ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi]+0x86): undefined reference to `google::protobuf::internal::LogFinisher::operator=(google::protobuf::internal::LogMessage&)'
main.cpp:(.text._ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi[_ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi]+0x8e): undefined reference to `google::protobuf::internal::LogMessage::~LogMessage()'
main.cpp:(.text._ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi[_ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi]+0xb2): undefined reference to `google::protobuf::internal::LogMessage::LogMessage(google::protobuf::LogLevel, char const*, int)'
main.cpp:(.text._ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi[_ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi]+0xc1): undefined reference to `google::protobuf::internal::LogMessage::operator<<(char const*)'
main.cpp:(.text._ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi[_ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi]+0xce): undefined reference to `google::protobuf::internal::LogFinisher::operator=(google::protobuf::internal::LogMessage&)'
main.cpp:(.text._ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi[_ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi]+0xd6): undefined reference to `google::protobuf::internal::LogMessage::~LogMessage()'
main.cpp:(.text._ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi[_ZNK6google8protobuf8internal20RepeatedPtrFieldBase3GetINS0_16RepeatedPtrFieldIN10tensorflow7NodeDefEE11TypeHandlerEEERKNT_8WeakTypeEi]+0xf5): undefined reference to `google::protobuf::internal::LogMessage::~LogMessage()'
collect2: error: ld returned 1 exit status
It seems that protobuf lib is missing. So I added also -ltensorflow_framework
It compile without errors, BUT i get this error:
[libprotobuf ERROR external/com_google_protobuf/src/google/protobuf/descriptor_database.cc:118] File already exists in database: google/protobuf/any.proto
[libprotobuf FATAL external/com_google_protobuf/src/google/protobuf/descriptor.cc:1367] CHECK failed: GeneratedDatabase()->Add(encoded_file_descriptor, size):
terminate called after throwing an instance of 'google::protobuf::FatalException'
what(): CHECK failed: GeneratedDatabase()->Add(encoded_file_descriptor, size):
Aborted (core dumped)
Why I'm getting those errors?
I already read this https://github.com/tensorflow/tensorflow/issues/14632 and this https://github.com/tensorflow/tensorflow/issues/40004 , but without luck.
Thx
I have some code, when I compile it, I got the following errors, and I don't know how to solve it. I have tried to add -L/usr/lib/x86_64-linux-gnu, -lboost_system and -lboost_filesystem, but I still got the same errors. I don't know how to fix this problem now, if anybody could help?
Agent.o: In function `boost::filesystem::path::append(char const*, std::codecvt<wchar_t, char, __mbstate_t> const&)':
/usr/include/boost/filesystem/path.hpp:307: undefined reference to `boost::filesystem::path::operator/=(char const*)'
Agent.o: In function `boost::filesystem::exists(boost::filesystem::path const&)':
/usr/include/boost/filesystem/operations.hpp:289: undefined reference to `boost::filesystem::detail::status(boost::filesystem::path const&, boost::system::error_code*)'
Agent.o: In function `boost::filesystem::create_directories(boost::filesystem::path const&)':
/usr/include/boost/filesystem/operations.hpp:399: undefined reference to `boost::filesystem::detail::create_directories(boost::filesystem::path const&, boost::system::error_code*)'
Agent.o: In function `boost::enable_if<boost::filesystem::path_traits::is_pathable<boost::decay<char [256]>::type>, boost::filesystem::path&>::type boost::filesystem::path::operator/=<char [256]>(char const (&) [256])':
/usr/include/boost/filesystem/path.hpp:302: undefined reference to `boost::filesystem::path::codecvt()'
collect2: error: ld returned 1 exit status
make: *** [player] Error 1
The related code are as following
bool Agent::openTupleLog()
{
std::string dir="~/Experiments/Nov/";
// create the log directory & file path string
try
{
boost::filesystem::path kaway_log( dir
#if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION == 2
# ifndef BOOST_FILESYSTEM_NO_DEPRECATED
, &boost::filesystem::native
# endif
#endif
);
if ( ! boost::filesystem::exists( kaway_log )
&& ! boost::filesystem::create_directories( kaway_log ) )
{
std::cerr << __FILE__ << ": " << __LINE__
<< ": can't create log directory '"
<< kaway_log.BOOST_FS_DIRECTORY_STRING() << "'" << std::endl;
return false;
}
kaway_log /= tuplesFilename;
M_kaway_log_name = kaway_log.BOOST_FS_FILE_STRING();
}
catch ( std::exception & e )
{
std::cerr << __FILE__ << ": " << __LINE__
<< " Exception caught! " << e.what()
<< "\nCould not create log directory '"
<< dir
<< "'" << std::endl;
return false;
}
// open the output file stream
M_kaway_log.open( M_kaway_log_name.c_str() );
if ( ! M_kaway_log.is_open() )
{
std::cerr << __FILE__ << ": " << __LINE__
<< ": can't open log_file " << M_kaway_log_name
<< std::endl;
return false;
}
return true;
}
Problem solved.
I asked a friend, he told me to add /usr/lib/x86_64-linux-gnu/libboost_filesystem.a -lboost_filesystem -lboost_system at the end of the command, then it works. He said:
The order of putting those flags are dependent, and thus I have to move the .a to very end. Then it ask for boost_system and thus I appended -lboost_system for its pleasure.
And note that it's libboost_filesystem.a, not libboost_filesystem.so
The following compile error i am facing when i compile a .cc file. i am using apache ignite libraries and c++ libraries to compile and jdk path is specified.
#include <iostream>
#include "ignite/ignite.h"
#include "ignite/ignition.h"
using namespace ignite;
using namespace cache;
int main()
{
IgniteConfiguration cfg;
cfg.jvmInitMem = 512;
cfg.jvmMaxMem = 512;
cfg.springCfgPath = "/home/ignite/DataGridTest.xml";
try
{
Ignite grid = Ignition::Start(cfg);
std::cout << std::endl;
std::cout << ">>> Cache put-get example started." << std::endl;
std::cout << std::endl;
Cache<int, int> cache = grid.GetCache<int, int>("mycache");
cache.Clear();
cache.Put(1, 1);
int orgFromCache = cache.Get(1);
std::cout << ">>> Retrieved value from cache: " << std::endl;
std::cout << orgFromCache << std::endl;
std::cout << std::endl;
Ignition::StopAll(false);
}
catch (IgniteError& err)
{
std::cout << "An error occurred: " << err.GetText() << std::endl;
}
std::cout << std::endl;
std::cout << ">>> Example finished, press 'Enter' to exit ..." << std::endl;
std::cout << std::endl;
return 0;
}
In command line:
gcc -I /usr/java/jdk1.8.0_131/include/ -I
/usr/java/jdk1.8.0_131/include/linux/ -I
$IGNITE_HOME/platforms/cpp/jni/include/ -I
$IGNITE_HOME/platforms/cpp/core/include/ -I
$IGNITE_HOME/platforms/cpp/common/os/linux/include/ -I
$IGNITE_HOME/platforms/cpp/examples/include/ DataGridTest.cc -o DataGridTest -lignite
/usr/bin/ld: /tmp/cc9zxSDP.o: undefined reference to symbol '_ZN6ignite3jni4java12JniErrorInfoD1Ev'
/usr/local/lib//libignite-jni-2.0.0.19668.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
Except for the libignite you also need to link to libignite-binary, libignite-common and libignite-jni.
I am using g++ -lkeyczar -lcrypto -o basic_encrypt -Wall -O2 base_encrypt.cpp to compile the following code:
#include <cassert>
#include <iostream>
#include <string>
#include <keyczar/keyczar.h>
void EncryptAndDecrypt(const std::string& location) {
keyczar::Keyczar* crypter = keyczar::Crypter::Read(location);
if (!crypter)
return;
std::string input = "Secret message";
std::string ciphertext;
std::cout << "Plaintext: " << input << std::endl;
bool result = crypter->Encrypt(input, &ciphertext);
if (result) {
std::cout << "Ciphertext (Base64w): " << ciphertext << std::endl;
std::string decrypted_input;
bool result = crypter->Decrypt(ciphertext, &decrypted_input);
if (result)
assert(input == decrypted_input);
}
delete crypter;
}
int main(int argc, char** argv) {
if (argc != 2) {
std::cout << "An absolute key set location must be provided as argument"
<< std::endl;
return 1; // error
}
// The first argument must represent the keyset's location
const std::string location(argv[1]);
EncryptAndDecrypt(location);
return 0;
}
Which is a tutorial taken from here
However, I am running into the following error:
/tmp/ccNlack3.o: In function `EncryptAndDecrypt(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
base_encrypt.cpp:(.text+0xf): undefined reference to `keyczar::Crypter::Read(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
collect2: ld returned 1 exit status
I am unable to solve this since I know that I am already giving the library flags while compiling. Why is it still unable to link correctly ?
Put the library flags at the end of the command line:
g++ -o basic_encrypt -Wall -O2 base_encrypt.cpp -lkeyczar -lcrypto
So i've got this very basic OOP example and i want to compile it in Xubuntu but I get errors
the CThermo.h file
class CThermo
{
public:
void SetTemp(int newTemp);
int ReturnTemp();
void ChangeTemp(int deltaTemp);
private:
int m_temp;
};
the CThermo.cpp file
#incude "CThermo.h"
void CThermo::SetTemp(int newTemp)
{
m_temp = newTemp;
}
int CThermo::ReturnTemp()
{
return m_temp;
}
void CThermo::ChangeTemp(int deltaTemp)
{
m_temp += deltaTemp;
}
the main.cpp file
#include "CThermo.h"
#include <iostream>
using std::cout;
int main()
{
CThermo roomTemp;
roomTemp.SetTemp(20);
cout << "the temp is : "<< roomTemp.ReturnTemp() << "\n";
roomTemp.ChangeTemp(5);
cout << "after changing the temp, the room temp is : " << roomTemp.ReturnTemp();
cout << "test";
return 0;
}
the command to compile is "g++ main.cpp -o Main"
and this are the errors I get
/tmp/ccXajxEY.o: In function `main':
main.cpp:(.text+0x1a): undefined reference to `CThermo::SetTemp(int)'
main.cpp:(.text+0x26): undefined reference to `CThermo::ReturnTemp()'
main.cpp:(.text+0x6c): undefined reference to `CThermo::ChangeTemp(int)'
main.cpp:(.text+0x78): undefined reference to `CThermo::ReturnTemp()'
collect2: error: ld returned 1 exit status
You have to compile both main.cpp and CThermo.cpp using:
g++ CThermo.cpp main.cpp -o Main