Simple
Create a src/main.rs that will be used as the defacto executable. You do not need to modify your Cargo.toml and this file will be compiled to a binary of the same name as the library.
The project contents:
% tree
.
├── Cargo.toml
└── src
    ├── lib.rs
    └── main.rs
Cargo.toml
[package]
name = "example"
version = "0.1.0"
edition = "2018"
src/lib.rs
use std::error::Error;
pub fn really_complicated_code(a: u8, b: u8) -> Result<u8, Box<dyn Error>> {
    Ok(a + b)
}
src/main.rs
fn main() {
    println!(
        "I'm using the library: {:?}",
        example::really_complicated_code(1, 2)
    );
}
And execute it:
% cargo run -q
I'm using the library: Ok(3)
Flexible
If you wish to control the name of the binary or have multiple binaries, you can create multiple binary source files in src/bin and the rest of your library sources in src. You can see an example in my project. You do not need to modify your Cargo.toml at all, and each source file in src/bin will be compiled to a binary of the same name.
The project contents:
% tree
.
├── Cargo.toml
└── src
    ├── bin
    │   └── mybin.rs
    └── lib.rs
Cargo.toml
[package]
name = "example"
version = "0.1.0"
edition = "2018"
src/lib.rs
use std::error::Error;
pub fn really_complicated_code(a: u8, b: u8) -> Result<u8, Box<dyn Error>> {
    Ok(a + b)
}
src/bin/mybin.rs
fn main() {
    println!(
        "I'm using the library: {:?}",
        example::really_complicated_code(1, 2)
    );
}
And execute it:
% cargo run --bin mybin -q
I'm using the library: Ok(3)
See also: